package protocolo;

import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.Iterator;

import monitor.ManagerObjetos;


public class Enviador extends Thread {	
	
	private ManagerObjetos managerObjetos;
	
	public ArrayList<Pedido> pedidos;
	private DatagramSocket socketPP;
	
	private final String IP_0 = "192.168.32.49";
	private final String IP_1 = "192.168.32.00";
	private final String IP_2 = "192.168.32.30";
	private final String IP_3 = "192.168.32.23";
	private final String IP_4 = "192.168.32.31";
	private final String IP_5 = "192.168.32.33";
	
	private final int PUERTO = 54321;
	
	public Enviador() {
		// Crea el socket  
		socketPP = null;
		try {
			socketPP = new DatagramSocket();
		} catch (SocketException e1) {
			// TODO Auto-generated catch block
			System.err.println("Error al crear el socket de envio de respeustas mias");
		}  
		
		pedidos = new ArrayList<Pedido>();
		
		try {
			managerObjetos = ManagerObjetos.getInstance(null);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.err.println("Error al instanciar el manager de objetos");
		}
	}
	
	
	//	 Mapeo de identificadores de objeto a direcciones IP
	public String getDireccionIP(int idAliado) {
		switch(idAliado) {
			case 0: return IP_0;
			case 1: return IP_1;
			case 2: return IP_2;
			case 3: return IP_3;
			case 4: return IP_4;
			case 5: return IP_5;
			default: return "Error";
		}
	}
	
	//	Mapeo de direcciones IP a identificadores de objeto 
	public int mapearIPAObjeto(String IP) {
		if (IP.equals(IP_0)) 
			return 0;
		else if (IP.equals(IP_1))
			return 1;
		else if (IP.equals(IP_2))
			return 2;
		else if (IP.equals(IP_3))
			return 3;
		else if (IP.equals(IP_4))
			return 4;
		else if (IP.equals(IP_5))
			return 5;
		else {
			System.err.println("Error al mapearDirecciones a identificadores de objeto");
			return -1;
		}
	}
	
	public void enviar(Pedido respuesta) {
		// Construyo la dirección del socket del receptor
		InetAddress ipAliado = null;
		int puertoAliado = respuesta.getPuerto();
		try {
			ipAliado = InetAddress.getByName(respuesta.getDireccionIP());
		} catch (UnknownHostException e1) {
			// TODO Auto-generated catch block
			System.err.println("Error al construir la ip de un aliado en InetAddress");
		}
		
	    // Creo el mensaje
	    byte[] cadena = respuesta.getByte();  
	    if (cadena.length != 1)
	    	System.err.println("Se quiere enviar una cadena que no tiene un byte, cadena bytes = " + cadena.length);
	    DatagramPacket mensaje = new DatagramPacket(cadena, cadena.length, ipAliado, puertoAliado);  
	 
	    // Envía el primer mensaje  
	    try {
	    	System.out.println("Se envio pedido: " + Integer.toBinaryString(cadena[0]));
	    	
			socketPP.send(mensaje);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.err.println("Error al enviar pedido a un aliado, la ip es: " + ipAliado);
		}
	}
	
	
	public void run() {
		
		while (true) {
			synchronized (pedidos) {
				if (! pedidos.isEmpty()) {
					Pedido pedido = pedidos.remove(0);
					if (! pedido.esAyuda()) {
						pedido.setPuerto(PUERTO);
						pedido.setIP(getDireccionIP(pedido.getIdObjetivo()));
						enviar(pedido);
					} else {
						ArrayList<Integer> aliadosCandidatos = managerObjetos.getAliadosActivos();
						Iterator<Integer> iter = aliadosCandidatos.iterator();
						while (iter.hasNext()) {
							int idObjeto = iter.next();
							pedido.setIP(getDireccionIP(idObjeto));
							System.err.println("Envie pedido ayuda a la direccion " + pedido.getDireccionIP());
							pedido.setPuerto(PUERTO);
							enviar(pedido);
						}
					}
				} 	
			}
			
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}

	}
	
	public void shutdown() {
		if (socketPP != null)
			socketPP.close();
	}
	

}
